package com.example.demo.service;

import org.flowable.bpmn.model.BpmnModel;
import org.flowable.cmmn.api.CmmnRuntimeService;
import org.flowable.cmmn.api.runtime.CaseInstance;
import org.flowable.dmn.api.DmnDecisionService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 三种引擎协同工作服务
 * 演示BPMN、DMN、CMMN如何协同处理复杂业务场景
 */
@Service
public class IntegratedWorkflowService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private DmnDecisionService dmnDecisionService;

    @Autowired
    private CmmnRuntimeService cmmnRuntimeService;

    /**
     * 场景1：BPMN + DMN 协同
     * 在BPMN流程中调用DMN决策服务
     */
    public String processLeaveRequestWithDecision(String employee, String reason, int days) {
        System.out.println("=== BPMN + DMN 协同工作 ===");
        
        // 1. 启动BPMN流程
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee", employee);
        variables.put("reason", reason);
        variables.put("days", days);
        
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveRequest", variables);
        System.out.println("BPMN流程已启动，实例ID：" + processInstance.getId());
        
        // 2. 在流程执行过程中调用DMN决策
        String decisionResult = executeLeaveDecision(employee, reason, days);
        System.out.println("DMN决策结果：" + decisionResult);
        
        // 3. 将决策结果设置回BPMN流程
        runtimeService.setVariable(processInstance.getId(), "dmnDecisionResult", decisionResult);
        
        return processInstance.getId();
    }

    /**
     * 场景2：BPMN + CMMN 协同
     * 在BPMN流程中启动CMMN案例
     */
    public String processComplaintWithBpmn(String customerName, String complaintDescription) {
        System.out.println("=== BPMN + CMMN 协同工作 ===");
        
        // 1. 启动BPMN流程处理投诉
        Map<String, Object> bpmnVariables = new HashMap<>();
        bpmnVariables.put("customerName", customerName);
        bpmnVariables.put("complaintDescription", complaintDescription);
        bpmnVariables.put("processType", "complaint");
        
        ProcessInstance bpmnInstance = runtimeService.startProcessInstanceByKey("complaintProcess", bpmnVariables);
        System.out.println("BPMN投诉流程已启动，实例ID：" + bpmnInstance.getId());
        
        // 2. 在BPMN流程中启动CMMN案例
        Map<String, Object> cmmnVariables = new HashMap<>();
        cmmnVariables.put("customerName", customerName);
        cmmnVariables.put("complaintDescription", complaintDescription);
        cmmnVariables.put("complaintHandler", "客服001");
        cmmnVariables.put("priority", "高");
        cmmnVariables.put("bpmnProcessId", bpmnInstance.getId()); // 关联BPMN流程
        
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                .caseDefinitionKey("customerComplaintCase")
                .variables(cmmnVariables)
                .start();
        
        System.out.println("CMMN案例已启动，案例ID：" + caseInstance.getId());
        
        // 3. 将CMMN案例ID设置回BPMN流程
        runtimeService.setVariable(bpmnInstance.getId(), "cmmnCaseId", caseInstance.getId());
        
        return bpmnInstance.getId();
    }

    /**
     * 场景3：DMN + CMMN 协同
     * 在CMMN案例中使用DMN进行决策
     */
    public String processComplaintWithDecision(String customerName, String complaintDescription, String complaintType) {
        System.out.println("=== DMN + CMMN 协同工作 ===");
        
        // 1. 启动CMMN案例
        Map<String, Object> cmmnVariables = new HashMap<>();
        cmmnVariables.put("customerName", customerName);
        cmmnVariables.put("complaintDescription", complaintDescription);
        cmmnVariables.put("complaintType", complaintType);
        cmmnVariables.put("complaintHandler", "客服001");
        
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                .caseDefinitionKey("customerComplaintCase")
                .variables(cmmnVariables)
                .start();
        
        System.out.println("CMMN案例已启动，案例ID：" + caseInstance.getId());
        
        // 2. 在案例处理过程中调用DMN决策
        String priorityDecision = executeComplaintPriorityDecision(complaintType, complaintDescription);
        System.out.println("DMN优先级决策结果：" + priorityDecision);
        
        // 3. 将决策结果设置回CMMN案例
        cmmnRuntimeService.setVariable(caseInstance.getId(), "complaintPriority", priorityDecision);
        cmmnRuntimeService.setVariable(caseInstance.getId(), "dmnDecisionApplied", true);
        
        return caseInstance.getId();
    }

    /**
     * 场景4：三种引擎完全集成
     * 复杂业务场景中三种引擎协同工作
     */
    public String processComplexBusinessScenario(String employee, String reason, int days, String customerName, String complaintDescription) {
        System.out.println("=== 三种引擎完全集成 ===");
        
        // 1. 使用DMN决策确定处理策略
        Map<String, Object> decisionInput = new HashMap<>();
        decisionInput.put("employee", employee);
        decisionInput.put("reason", reason);
        decisionInput.put("days", days);
        decisionInput.put("hasComplaint", customerName != null);
        
        String processingStrategy = executeProcessingStrategyDecision(decisionInput);
        System.out.println("处理策略决策结果：" + processingStrategy);
        
        String result = "";
        
        if ("standard_process".equals(processingStrategy)) {
            // 2a. 标准流程：使用BPMN处理
            result = processLeaveRequestWithDecision(employee, reason, days);
            
        } else if ("complaint_process".equals(processingStrategy)) {
            // 2b. 投诉流程：使用CMMN处理
            result = processComplaintWithDecision(customerName, complaintDescription, "service");
            
        } else if ("hybrid_process".equals(processingStrategy)) {
            // 2c. 混合流程：BPMN + CMMN + DMN
            result = processHybridScenario(employee, reason, days, customerName, complaintDescription);
        }
        
        return result;
    }

    /**
     * 混合场景处理
     */
    private String processHybridScenario(String employee, String reason, int days, String customerName, String complaintDescription) {
        System.out.println("=== 混合场景处理 ===");
        
        // 1. 启动BPMN流程
        Map<String, Object> bpmnVariables = new HashMap<>();
        bpmnVariables.put("employee", employee);
        bpmnVariables.put("reason", reason);
        bpmnVariables.put("days", days);
        bpmnVariables.put("hasComplaint", true);
        
        ProcessInstance bpmnInstance = runtimeService.startProcessInstanceByKey("leaveRequest", bpmnVariables);
        
        // 2. 启动CMMN案例
        Map<String, Object> cmmnVariables = new HashMap<>();
        cmmnVariables.put("customerName", customerName);
        cmmnVariables.put("complaintDescription", complaintDescription);
        cmmnVariables.put("complaintHandler", "客服001");
        cmmnVariables.put("priority", "中");
        cmmnVariables.put("relatedBpmnProcess", bpmnInstance.getId());
        
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                .caseDefinitionKey("customerComplaintCase")
                .variables(cmmnVariables)
                .start();
        
        // 3. 使用DMN进行综合决策
        Map<String, Object> decisionInput = new HashMap<>();
        decisionInput.put("employeeLevel", determineEmployeeLevel(employee));
        decisionInput.put("days", days);
        decisionInput.put("leaveType", determineLeaveType(reason));
        decisionInput.put("complaintSeverity", "中");
        
        var decisionResult = dmnDecisionService.createExecuteDecisionBuilder()
                .decisionKey("leaveApprovalDecision")
                .variables(decisionInput)
                .executeWithSingleResult();
        
        if (decisionResult != null) {
            String approvalResult = (String) decisionResult.get("approvalResult");
            String approverLevel = (String) decisionResult.get("approverLevel");
            
            // 4. 将决策结果同步到两个流程
            runtimeService.setVariable(bpmnInstance.getId(), "approvalResult", approvalResult);
            runtimeService.setVariable(bpmnInstance.getId(), "approverLevel", approverLevel);
            runtimeService.setVariable(bpmnInstance.getId(), "cmmnCaseId", caseInstance.getId());
            
            cmmnRuntimeService.setVariable(caseInstance.getId(), "approvalResult", approvalResult);
            cmmnRuntimeService.setVariable(caseInstance.getId(), "approverLevel", approverLevel);
            cmmnRuntimeService.setVariable(caseInstance.getId(), "bpmnProcessId", bpmnInstance.getId());
        }
        
        System.out.println("混合场景处理完成");
        System.out.println("- BPMN流程ID：" + bpmnInstance.getId());
        System.out.println("- CMMN案例ID：" + caseInstance.getId());
        
        return bpmnInstance.getId() + "|" + caseInstance.getId();
    }

    /**
     * 执行请假决策
     */
    private String executeLeaveDecision(String employee, String reason, int days) {
        Map<String, Object> decisionInput = new HashMap<>();
        decisionInput.put("employeeLevel", determineEmployeeLevel(employee));
        decisionInput.put("days", days);
        decisionInput.put("leaveType", determineLeaveType(reason));
        
        try {
            var decisionResult = dmnDecisionService.createExecuteDecisionBuilder()
                    .decisionKey("leaveApprovalDecision")
                    .variables(decisionInput)
                    .executeWithSingleResult();
            
            if (decisionResult != null) {
                return (String) decisionResult.get("approvalResult");
            }
        } catch (Exception e) {
            System.err.println("DMN决策执行失败：" + e.getMessage());
        }
        
        return "需要审批";
    }

    /**
     * 执行投诉优先级决策
     */
    private String executeComplaintPriorityDecision(String complaintType, String description) {
        // 这里可以调用另一个DMN决策表
        if (description.contains("紧急") || description.contains("严重")) {
            return "高";
        } else if (description.contains("一般")) {
            return "中";
        } else {
            return "低";
        }
    }

    /**
     * 执行处理策略决策
     */
    private String executeProcessingStrategyDecision(Map<String, Object> input) {
        String employee = (String) input.get("employee");
        Boolean hasComplaint = (Boolean) input.get("hasComplaint");
        Integer days = (Integer) input.get("days");
        
        if (hasComplaint) {
            return "hybrid_process";
        } else if (days > 10) {
            return "complaint_process";
        } else {
            return "standard_process";
        }
    }

    /**
     * 获取协同工作状态
     */
    public Map<String, Object> getIntegratedWorkflowStatus(String bpmnProcessId, String cmmnCaseId) {
        Map<String, Object> status = new HashMap<>();
        
        if (bpmnProcessId != null) {
            ProcessInstance bpmnInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(bpmnProcessId)
                    .singleResult();
            
            if (bpmnInstance != null) {
                status.put("bpmnStatus", "运行中");
                status.put("bpmnVariables", bpmnInstance.getProcessVariables());
                
                List<Task> bpmnTasks = taskService.createTaskQuery()
                        .processInstanceId(bpmnProcessId)
                        .list();
                status.put("bpmnActiveTasks", bpmnTasks.size());
            }
        }
        
        if (cmmnCaseId != null) {
            CaseInstance cmmnInstance = cmmnRuntimeService.createCaseInstanceQuery()
                    .caseInstanceId(cmmnCaseId)
                    .singleResult();
            
            if (cmmnInstance != null) {
                status.put("cmmnStatus", "运行中");
                status.put("cmmnVariables", cmmnInstance.getCaseVariables());
            }
        }
        
        return status;
    }

    private String determineEmployeeLevel(String employee) {
        if (employee.contains("经理") || employee.contains("Manager")) {
            return "经理";
        } else if (employee.contains("主管") || employee.contains("Lead")) {
            return "主管";
        } else {
            return "普通员工";
        }
    }

    private String determineLeaveType(String reason) {
        if (reason.contains("病") || reason.contains("医院") || reason.contains("生病")) {
            return "病假";
        } else if (reason.contains("事") || reason.contains("个人")) {
            return "事假";
        } else if (reason.contains("年") || reason.contains("旅游")) {
            return "年假";
        } else {
            return "事假";
        }
    }
}
